// // AudioPlayer.tsx
// import { useEffect, useState, useCallback } from 'react';
// import {
//     IconLoader,
//     IconPlayerPauseFilled,
//     IconPlayerPlayFilled,
//     IconRefresh,
// } from '@tabler/icons-react';
// import * as Tone from 'tone';
// // 导入自定义组件（需同步迁移 Visualizer，此处先假设已迁移）
// // import Visualizer from '../lib/components/Visualizer';
// // // 导入音频引擎模块（与 Svelte 共用，路径需匹配实际项目结构）
// // import ChordProgression from '../lib/engine/Chords/ChordProgression';
// // import intervalWeights from '../lib/engine/Chords/IntervalWeights';
// // import Keys from '../lib/engine/Chords/Keys';
// // import { fiveToFive } from '../lib/engine/Chords/MajorScale';
// // import Hat from '../lib/engine/Drums/Hat';
// // import Kick from '../lib/engine/Drums/Kick';
// // import Noise from '../lib/engine/Drums/Noise';
// // import Snare from '../lib/engine/Drums/Snare';
// // import Piano from '../lib/engine/Piano/Piano';

// // 常量定义（与 Svelte 一致）
// const STORAGE_KEY = 'Volumes';
// const DEFAULT_VOLUMES = {
//     rain: 1,
//     thunder: 1,
//     campfire: 1,
//     jungle: 1,
//     main_track: 1,
// };

// // 线性音量转 dB（工具函数）
// const linearToDb = (value: number) =>
//     value === 0 ? -Infinity : 20 * Math.log10(value);

// const AudioPlayer = () => {
//     // 1. 状态管理：替代 Svelte 的 let 响应式变量
//     const [volumes, setVolumes] = useState(DEFAULT_VOLUMES);
//     const [key, setKey] = useState('C');
//     const [progression, setProgression] = useState<any[]>([]); // 实际项目建议定义 Chord 类型
//     const [scale, setScale] = useState<string[]>([]);
//     const [progress, setProgress] = useState(0);
//     const [scalePos, setScalePos] = useState(0);
//     const [pianoLoaded, setPianoLoaded] = useState(false);
//     const [kickLoaded, setKickLoaded] = useState(false);
//     const [snareLoaded, setSnareLoaded] = useState(false);
//     const [hatLoaded, setHatLoaded] = useState(false);
//     const [contextStarted, setContextStarted] = useState(false);
//     const [genChordsOnce, setGenChordsOnce] = useState(false);
//     const [kickOff, setKickOff] = useState(false);
//     const [snareOff, setSnareOff] = useState(false);
//     const [hatOff, setHatOff] = useState(false);
//     const [melodyDensity, setMelodyDensity] = useState(0.33);
//     const [melodyOff, setMelodyOff] = useState(false);
//     const [isPlaying, setIsPlaying] = useState(false);

//     // 2. 音频核心实例：用 useRef 存储（避免 useState 触发不必要渲染）
//     const [cmp, setCmp] = useState<Tone.Compressor | null>(null);
//     const [lpf, setLpf] = useState<Tone.Filter | null>(null);
//     const [vol, setVol] = useState<Tone.Volume | null>(null);
//     const [pn, setPn] = useState<any>(null); // Piano 实例
//     const [kickSampler, setKickSampler] = useState<any>(null); // Kick 实例
//     const [snareSampler, setSnareSampler] = useState<any>(null); // Snare 实例
//     const [hatSampler, setHatSampler] = useState<any>(null); // Hat 实例
//     // 音频序列实例
//     const [chordsSeq, setChordsSeq] = useState<Tone.Sequence | null>(null);
//     const [melodySeq, setMelodySeq] = useState<Tone.Sequence | null>(null);
//     const [kickLoopSeq, setKickLoopSeq] = useState<Tone.Sequence | null>(null);
//     const [snareLoopSeq, setSnareLoopSeq] = useState<Tone.Sequence | null>(null);
//     const [hatLoopSeq, setHatLoopSeq] = useState<Tone.Sequence | null>(null);

//     // 3. 响应式计算：替代 Svelte 的 $: 声明
//     const allSamplesLoaded = pianoLoaded && kickLoaded && snareLoaded && hatLoaded;
//     const activeProgressionIndex = (progress + 7) % 8;
//     const isTransportStarted = Tone.Transport.state === 'started';


//     // 4. 初始化音频链和乐器：替代 Svelte 的 onMount 初始化逻辑
//     useEffect(() => {
//         // 读取本地存储音量
//         const savedVolumes = JSON.parse(localStorage.getItem(STORAGE_KEY) || 'null') || DEFAULT_VOLUMES;
//         setVolumes(savedVolumes);

//         // 初始化音频效果链
//         const newCmp = new Tone.Compressor({
//             threshold: -6,
//             ratio: 3,
//             attack: 0.5,
//             release: 0.1,
//         });
//         const newLpf = new Tone.Filter(2000, 'lowpass');
//         const newVol = new Tone.Volume(linearToDb(savedVolumes.main_track));
//         Tone.Master.chain(newCmp, newLpf, newVol);
//         Tone.Transport.bpm.value = 156;
//         Tone.Transport.swing = 1;

//         setCmp(newCmp);
//         setLpf(newLpf);
//         setVol(newVol);

//         // 初始化乐器（回调函数更新加载状态）
//         const newPiano = new Piano(() => setPianoLoaded(true)).sampler;
//         const newKick = new Kick(() => setKickLoaded(true)).sampler;
//         const newSnare = new Snare(() => setSnareLoaded(true)).sampler;
//         const newHat = new Hat(() => setHatLoaded(true)).sampler;

//         setPn(newPiano);
//         setKickSampler(newKick);
//         setSnareSampler(newSnare);
//         setHatSampler(newHat);

//         // 初始化音频序列
//         const newChordsSeq = new Tone.Sequence(
//             () => playChord(),
//             [""],
//             "1n"
//         );
//         const newMelodySeq = new Tone.Sequence(
//             () => playMelody(),
//             [""],
//             "8n"
//         );
//         const newKickLoopSeq = new Tone.Sequence(
//             (time, note: string) => {
//                 if (!kickOff && kickSampler) {
//                     if (note === "C4" && Math.random() < 0.9) {
//                         kickSampler.triggerAttack(note);
//                     } else if (note === "." && Math.random() < 0.1) {
//                         kickSampler.triggerAttack("C4");
//                     }
//                 }
//             },
//             ["C4", "", "", "", "", "", "", "C4", "C4", "", ".", "", "", "", "", ""],
//             "8n"
//         );
//         const newSnareLoopSeq = new Tone.Sequence(
//             (time, note: string) => {
//                 if (!snareOff && snareSampler) {
//                     if (note !== "" && Math.random() < 0.8) {
//                         snareSampler.triggerAttack(note);
//                     }
//                 }
//             },
//             ["", "C4"],
//             "2n"
//         );
//         const newHatLoopSeq = new Tone.Sequence(
//             (time, note: string) => {
//                 if (!hatOff && hatSampler) {
//                     if (note !== "" && Math.random() < 0.8) {
//                         hatSampler.triggerAttack(note);
//                     }
//                 }
//             },
//             ["C4", "C4", "C4", "C4", "C4", "C4", "C4", "C4"],
//             "4n"
//         );

//         // 开启序列人性化（避免机械感）
//         newChordsSeq.humanize = true;
//         newMelodySeq.humanize = true;
//         newKickLoopSeq.humanize = true;
//         newSnareLoopSeq.humanize = true;
//         newHatLoopSeq.humanize = true;

//         setChordsSeq(newChordsSeq);
//         setMelodySeq(newMelodySeq);
//         setKickLoopSeq(newKickLoopSeq);
//         setSnareLoopSeq(newSnareLoopSeq);
//         setHatLoopSeq(newHatLoopSeq);

//         // 监听空格键（播放/暂停）
//         const handleKeydown = (e: KeyboardEvent) => {
//             if (e.code === 'Space') {
//                 e.preventDefault();
//                 handleButtonAction();
//             }
//         };
//         window.addEventListener('keydown', handleKeydown);

//         // 监听本地存储音量变化（每 100ms 检查一次）
//         const volumeInterval = setInterval(() => {
//             const updatedVol = JSON.parse(localStorage.getItem(STORAGE_KEY) || 'null') || DEFAULT_VOLUMES;
//             setVolumes(updatedVol);
//             if (vol) vol.volume.value = linearToDb(updatedVol.main_track);
//         }, 100);

//         // 清理函数：替代 Svelte 的 onDestroy
//         return () => {
//             // 停止音频
//             if (Tone.Transport.state === 'started') {
//                 Noise.stop();
//                 Tone.Transport.stop();
//             }
//             // 移除事件监听
//             window.removeEventListener('keydown', handleKeydown);
//             // 清除定时器
//             clearInterval(volumeInterval);
//             // 销毁音频实例（避免内存泄漏）
//             newChordsSeq.dispose();
//             newMelodySeq.dispose();
//             newKickLoopSeq.dispose();
//             newSnareLoopSeq.dispose();
//             newHatLoopSeq.dispose();
//             newCmp.dispose();
//             newLpf.dispose();
//             newVol.dispose();
//         };
//     }, []); // 空依赖：仅组件挂载时执行一次


//     // 5. 自动初始化音频上下文：替代 Svelte 的 $: if (allSamplesLoaded && !contextStarted)
//     useEffect(() => {
//         if (allSamplesLoaded && !contextStarted) {
//             startAudioContext();
//             generateProgression();
//         }
//     }, [allSamplesLoaded, contextStarted]); // 依赖变化时执行


//     // 6. 核心业务函数（与 Svelte 逻辑一致，适配 React 状态更新）
//     const startAudioContext = useCallback(async () => {
//         await Tone.start();
//         setContextStarted(true);
//     }, []);

//     const generateProgression = useCallback(() => {
//         const _scale = fiveToFive;
//         const newKey = Keys[Math.floor(Math.random() * Keys.length)];
//         const newScale = Tone.Frequency(newKey + '5')
//             .harmonize(_scale)
//             .map((f) => Tone.Frequency(f).toNote());
//         const newProgression = ChordProgression.generate(8);
//         const newScalePos = Math.floor(Math.random() * _scale.length);

//         setKey(newKey);
//         setProgress(0);
//         setProgression(newProgression);
//         setScale(newScale);
//         setGenChordsOnce(true);
//         setScalePos(newScalePos);
//     }, []);

//     const nextChord = useCallback(() => {
//         const nextProgress = progress === progression.length - 1 ? 0 : progress + 1;
//         const nextKickOff = Math.random() < 0.15;
//         const nextSnareOff = Math.random() < 0.2;
//         const nextHatOff = Math.random() < 0.25;
//         const nextMelodyDensity = Math.random() * 0.3 + 0.2;
//         const nextMelodyOff = Math.random() < 0.25;

//         if (progress === 4) {
//             setProgress(nextProgress);
//             setKickOff(nextKickOff);
//             setSnareOff(nextSnareOff);
//             setHatOff(nextHatOff);
//         } else if (progress === 0) {
//             setProgress(nextProgress);
//             setKickOff(nextKickOff);
//             setSnareOff(nextSnareOff);
//             setHatOff(nextHatOff);
//             setMelodyDensity(nextMelodyDensity);
//             setMelodyOff(nextMelodyOff);
//         } else {
//             setProgress(nextProgress);
//         }
//     }, [progress, progression.length]);

//     const playChord = useCallback(() => {
//         if (!pn || !progression.length) return;
//         const chord = progression[progress];
//         const root = Tone.Frequency(key + '3').transpose(chord.semitoneDist);
//         const size = 4;
//         const voicing = chord.generateVoicing(size);
//         const notes = Tone.Frequency(root)
//             .harmonize(voicing)
//             .map((f) => Tone.Frequency(f).toNote());
//         pn.triggerAttackRelease(notes, '1n');
//         nextChord();
//     }, [pn, progression, progress, key, nextChord]);

//     const playMelody = useCallback(() => {
//         if (!pn || melodyOff || !(Math.random() < melodyDensity) || !scale.length) return;

//         const descendRange = Math.min(scalePos, 7) + 1;
//         const ascendRange = Math.min(scale.length - scalePos, 7);

//         let descend = descendRange > 1;
//         let ascend = ascendRange > 1;

//         if (descend && ascend) {
//             ascend = Math.random() > 0.5 ? !descend : descend;
//             descend = !ascend;
//         }

//         const weights = descend
//             ? intervalWeights.slice(0, descendRange)
//             : intervalWeights.slice(0, ascendRange);
//         const sum = weights.reduce((prev, curr) => prev + curr, 0);
//         const normalizedWeights = weights.map((w) => w / sum);
//         // 累加权重（用于随机选择）
//         for (let i = 1; i < normalizedWeights.length; i++) {
//             normalizedWeights[i] += normalizedWeights[i - 1];
//         }

//         const randomWeight = Math.random();
//         let scaleDist = 0;
//         while (scaleDist < normalizedWeights.length && randomWeight > normalizedWeights[scaleDist]) {
//             scaleDist++;
//         }

//         const scalePosChange = descend ? -scaleDist : scaleDist;
//         const newScalePos = scalePos + scalePosChange;
//         setScalePos(newScalePos);

//         pn.triggerAttackRelease(scale[newScalePos], '2n');
//     }, [pn, melodyOff, melodyDensity, scale, scalePos, intervalWeights]);

//     const toggle = useCallback(async () => {
//         setProgress(0);
//         if (Tone.Transport.state === 'started') {
//             // 暂停逻辑
//             Noise.stop();
//             await Tone.Transport.stop();
//             // 停止所有序列
//             chordsSeq?.stop();
//             melodySeq?.stop();
//             kickLoopSeq?.stop();
//             snareLoopSeq?.stop();
//             hatLoopSeq?.stop();
//             setIsPlaying(false);
//         } else {
//             // 播放逻辑
//             await Tone.start();
//             await Tone.Transport.start();
//             Noise.start(0);
//             // 启动所有序列
//             chordsSeq?.start(0);
//             melodySeq?.start(0);
//             kickLoopSeq?.start(0);
//             snareLoopSeq?.start(0);
//             hatLoopSeq?.start(0);
//             setIsPlaying(true);
//         }
//     }, [chordsSeq, melodySeq, kickLoopSeq, snareLoopSeq, hatLoopSeq]);

//     const handleButtonAction = useCallback(() => {
//         if (!allSamplesLoaded) {
//             return; // 样本未加载，按钮禁用
//         } else if (!contextStarted) {
//             startAudioContext(); // 初始化音频上下文
//         } else if (!genChordsOnce) {
//             return; // 和弦未生成，无法播放
//         } else {
//             toggle(); // 正常播放/暂停
//         }
//     }, [allSamplesLoaded, contextStarted, genChordsOnce, startAudioContext, toggle]);


//     // 7. JSX 渲染：替代 Svelte 的 markup（条件渲染 + 循环）
//     return (
//         <div>
//             {/* 控制按钮区域 */}
//             <div className="controls">
//                 <button
//                     className="play-button"
//                     onClick={handleButtonAction}
//                     disabled={!allSamplesLoaded}
//                     aria-label={isPlaying ? "Pause" : "Play"}
//                 >
//                     {!allSamplesLoaded ? (
//                         <IconLoader size={30} className="spinning" />
//                     ) : !contextStarted ? (
//                         <span className="context-text">Initialize Audio</span>
//                     ) : !genChordsOnce ? (
//                         <IconPlayerPlayFilled size={30} className="disabled" />
//                     ) : isPlaying ? (
//                         <IconPlayerPauseFilled size={30} />
//                     ) : (
//                         <IconPlayerPlayFilled size={30} />
//                     )}
//                 </button>
//                 <button
//                     className="generateBtn"
//                     onClick={generateProgression}
//                     aria-label="Generate New Chord Progression"
//                 >
//                     <IconRefresh size={16} />
//                 </button>
//             </div>

//             {/* 和弦进程列表 */}
//             {allSamplesLoaded && contextStarted && genChordsOnce && (
//                 <ol className="progressionList">
//                     <li className="key" id="blurred">{key}</li>
//                     {progression.map((chord, idx) => (
//                         <li
//                             key={idx} // 实际项目建议用 chord.id，避免 idx 不稳定
//                             id="blurred"
//                             className={idx === activeProgressionIndex ? "live" : ""}
//                         >
//                             {chord.degree}
//                         </li>
//                     ))}
//                 </ol>
//             )}

//             {/* 音频可视化器 */}
//             {isTransportStarted && (
//                 <div className="visualizer-container">
//                     <Visualizer audio={Tone.Master} />
//                 </div>
//             )}

//         </div>
//     );
// };

// export default AudioPlayer;
